package com.lagou.consumer;

import com.lagou.loadbalance.DefaultLoadBalancer;
import com.lagou.register.ICompleteCallback;
import com.lagou.rpc.*;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.InetSocketAddress;
import java.util.concurrent.atomic.AtomicInteger;

public class RpcConsumer {

    private static AtomicInteger requestId = new AtomicInteger(0);

    private DefaultLoadBalancer loadBalancer = DefaultLoadBalancer.getInstance();


    //1.创建一个代理对象
    public Object createProxy(final Class<?> serviceClass, ICompleteCallback callback){
        //借助JDK动态代理生成代理对象
        return  Proxy.newProxyInstance(RpcConsumer.class.getClassLoader(), new Class<?>[]{serviceClass}, new InvocationHandler() {
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                /**
                 * 负载均衡,选择一个server服务
                 * 由于时间关系, 并没有实现通过接口来进行server分组, 其实注册到zookeeper可以是一个三级目录
                 *
                 * |_ /simple_rpc  (rpc第一级根目录)
                 *    |_ /<暴露的接口名作为服务分组目录> (第二级服务分组)
                 *       |_ /<ip>:<port>     (第三级同一服务的不同进程实例副本, value可以存一些通信状态, 用以支持不同负载均衡算法)
                 */

                //此处默认都是同一类服务, 选取一个节点进行通信
                InetSocketAddress server = loadBalancer.chooseServer();


                /**
                 * 构造协议请求
                 */
                RpcRequest req = new RpcRequest();
                req.setClassName(serviceClass);
                req.setMethodName(method.getName());
                req.setParameterTypes(method.getParameterTypes());
                req.setParameters(args);
                req.setRequestId(String.valueOf(requestId.incrementAndGet()));

                /**
                 * 开始请求, 这里将异步转同步, 并没有使用Future
                 */
                final Object[] res = {null};

                loadBalancer.getPool().write(server, req, callback);

                return null;
            }
        });
    }
}
